﻿#define _CRT_SECURE_NO_WARNINGS 1
// 原题连接：
/*
【题目描述】
在一个给定形状的棋盘（形状可能是不规则的）上面摆放棋子，棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列，请编程求解对于给定形状和大小的棋盘，摆放 k
 个棋子的所有可行的摆放方案 C
。

【输入】
输入含有多组测试数据。

每组数据的第一行是两个正整数n,k
，用一个空格隔开，表示了将在一个n×n
的矩阵内描述棋盘，以及摆放棋子的数目。 (n≤8,k≤n)
当为−1−1
时表示输入结束。

随后的n
行描述了棋盘的形状：每行有n
个字符，其中 #
 表示棋盘区域，.
 表示空白区域（数据保证不出现多余的空白行或者空白列）。

【输出】
对于每一组数据，给出一行输出，输出摆放的方案数目C
（数据保证C<231
）。

【输入样例】
2 1
#.
.#
4 4
...#
..#.
.#..
#...
-1 -1
【输出样例】
2
1

*/

// 开始解题：
// 方法——dfs
#include <iostream>
#include <string.h>
using namespace std;

int N = 0, K = 0;
int ret = 0;
char board[10][10];
bool vis[10][10], check_row[10], check_col[10];

void dfs(int row, int k) {
	if (0 == k) {
		ret++;
		return;
	}
	if (row == N + 1) {
		return;
	}
	for (int i = row; i <= N; i++) {
		for (int j = 1; j <= N; j++) {
			if (board[i][j] == '#' && !vis[i][j] && !check_row[i] && !check_col[j]) {
				vis[i][j] = true;
				check_row[i] = true;
				check_col[j] = true;
				dfs(i + 1, k - 1);
				// 恢复现场
				vis[i][j] = false;
				check_row[i] = false;
				check_col[j] = false;
			}
		}
	}
}

int main() {
	while (true) {
		ret = 0;
		memset(vis, 0, sizeof(vis));
		memset(check_row, 0, sizeof(check_row));
		memset(check_col, 0, sizeof(check_col));

		cin >> N >> K;
		if (-1 == N && -1 == K) {
			break;
		}
		for (int i = 1; i <= N; i++) {
			for (int j = 1; j <= N; j++) {
				cin >> board[i][j];
			}
		}
		dfs(1, K);
		cout << ret << endl;
	}
	return 0;
}